import javax.media.j3d.*;
import javax.vecmath.*;

/*
 * Generates the geometry required by walls in a room. The walls are made from
 * 8 vertices, defining 4 walls.
 *
 *        V6-----V7
 *       /|     / |
 *      / |    /  |
 *    V2------V3  |
 *    |   |   |   |
 *    |   V4--|-- V5
 *    |  /    |  /
 *    | /     | /
 *    V0------V1
 *
 * The walls are madeof the following vertices:
 *  North => [V4, V5, V6, V7]
 *  South => [V0, V1, V2, V3]
 *  East  => [V3, V7, V1, V5]
 *  West  => [V0, V4, V2, V6]
 *
 * Utilises an indexed quad array method to simplify creations.
 */

class BoxGeometry extends IndexedQuadArray {

    private Point3f[] vertices = {
        new Point3f(-1, -1, -1),
        new Point3f(1, -1, -1),
        new Point3f(-1, 1, -1),
        new Point3f(1, 1, -1),
        new Point3f(-1, -1, 1),
        new Point3f(1, -1 , 1),
        new Point3f(-1, 1, 1),
        new Point3f(1, 1, 1)
    };

    private int[] vertexIndices = {
        2, 3, 1, 0,
    	4, 5, 7, 6,
        3, 7, 5, 1,
    	0, 4, 6, 2,
        6, 7, 3, 2,
        0, 1, 5, 4
    };

    private Vector3f[] normals = {
        new Vector3f(),
        new Vector3f(),
        new Vector3f(),
        new Vector3f(),
        new Vector3f(),
        new Vector3f()
    };

    private int[] normalIndices = {
        0, 0, 0, 0,
        1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3, 3,
        4, 4, 4, 4,
        5, 5, 5, 5
    };
    
    private Point2f[] textureCoordinates = {
        new Point2f(0, 0),
        new Point2f(1, 0),
        new Point2f(0, 1),
        new Point2f(1, 1)
    };

    private int[] textureIndices = {
        0, 1, 2, 3,
        0, 1, 2, 3,
        0, 1, 2, 3,
        0, 1, 2, 3,
        0, 1, 2, 3,
        0, 1, 2, 3
    };


    public BoxGeometry (){
		super(8, IndexedQuadArray.COORDINATES | IndexedQuadArray.NORMALS | IndexedQuadArray.TEXTURE_COORDINATE_2, 24);
        initialise();
    }

    private void initialise () {
        this.setCoordinates(0, vertices);
        this.setCoordinateIndices(0, vertexIndices);
        this.generateNormals();
        this.setNormals(0, normals);
        this.setNormalIndices(0, normalIndices);
        this.setTextureCoordinates(0, textureCoordinates);
        this.setTextureCoordinateIndices(0, textureIndices);
    }

    /**
     * auto generate the normals for these surface. Sure we could hardcode them, but
     * this is more fun.
     */
    private void generateNormals(){
        Vector3f v1 = new Vector3f();
        Vector3f v2 = new Vector3f();
        int idx = 0;
        for (int i = 0; i < vertexIndices.length - 3; i += 4){
            v1.sub(vertices[vertexIndices[i]], vertices[vertexIndices[i + 1]]);
            v2.sub(vertices[vertexIndices[i]], vertices[vertexIndices[i + 3]]);
            normals[idx].cross(v2, v1);
            normals[idx++].negate();
        }
    }
}
